<template>
    <TypeBar _title="模型"></TypeBar>
    <div class="model-cards-container">
        <div v-for="(card, cindex) in _cardlist">
            <div class="model-card">
                <div class="model-name">{{ card.name }}</div>
                <div class="model-eng-name">{{ card.eng_name }}</div>
                <div class="model-tags">
                    <el-tag class="model-tag" type="primary">{{ card.type }}</el-tag>
                    <el-tag class="model-tag" type="primary">{{ card.framework }}</el-tag>
                </div>
                <div class="model-desc">
                    {{ card.desc }}
                </div>
                <div class="model-footer">
                    <div class="model-update-time">更新时间: {{ card.update_time }}</div>
                </div>
                <div class="train-btn">
                    <el-button type="primary" :icon="MagicStick" @click="handleTrainModel(card)">开始训练</el-button>
                </div>
                <div class="more-btn">
                    <el-tooltip content="更多" placement="bottom" effect="light">
                        <el-dropdown trigger="click">
                            <el-button link type="primary" size="large">
                                <MoreFilled class="more-icon" />
                            </el-button>
                            <template #dropdown>
                                <el-dropdown-menu>
                                    <el-dropdown-item :icon="InfoFilled" @click="handleModelInfo(card)"> 模型信息
                                    </el-dropdown-item>
                                    <el-dropdown-item :icon="Promotion" @click="handleModelInfer(card)"> 模型推理
                                    </el-dropdown-item>
                                    <el-dropdown-item :icon="Histogram" @click="handleModelEval(card)"> 模型评测
                                    </el-dropdown-item>
                                </el-dropdown-menu>
                            </template>
                        </el-dropdown>
                    </el-tooltip>
                </div>
            </div>
        </div>
    </div>
    <!-- config model dialog -->
    <el-dialog v-model="_dialogFormVisible" :title="_modelSettingStatus ? '配置数据集' : '配置模型'" align-center width="500px"
        :before-close="handleBeforeClose">
        <div v-if="_modelSettingStatus === 0" class="model-configs-panel">
            <div class="model-configs-title">模型配置</div>
            <el-select class="model-configs-selector" v-model="_model_config" placeholder="选择模型配置" style="width: 240px"
                @change="onChangeModelConfig">
                <el-option v-for="config in _model_configs" :key="config" :label="config" :value="config" />
            </el-select>
        </div>
        <div v-if="_modelSettingStatus === 0 && _model_config" class="model-configs-panel">
            <div class="model-configs-title">总参数量</div>
            <div class="model-configs-value">{{ _model_total_params }}</div>
        </div>
        <div v-if="_modelSettingStatus === 0 && _model_config" class="model-configs-panel">
            <div class="model-configs-title">训练参数量</div>
            <div class="model-configs-value">{{ _model_trainable_params }}</div>
        </div>
        <div v-if="_modelSettingStatus === 1" class="datasets-panel">
            <el-table :data="_datasets" highlight-current-row style="width: 100%" max-height="250"
                :header-cell-style="headerCellStyle" :cell-style="cellStyle" @row-click="handleRowClick">
                <el-table-column prop="id" label="id" width="140" />
                <el-table-column prop="dataset_name" label="dataset_name" min-width="150" />
            </el-table>
        </div>
        <div v-if="_modelSettingStatus === 1" class="subsets-panel">
            <div class="subset-title">配置训练/验证/测试集</div>
            <div v-for="(subset, index) in subsetsInfo" :key="subset.id">
                <div class="subset-info">
                    <div class="subset-type">{{ formattedSubsetType(subset.subset_type) }}</div>
                    <div class="subset-dir">
                        <FolderOpened v-if="!subset.editing && subset.image_dir"
                            class="directory-item-title-icon yellow" />
                        <div v-if="!subset.editing">{{ subset.image_dir }}</div>
                    </div>
                    <el-select v-if="subset.editing" v-model="subset.image_dir" placeholder="选择数据集类型" size="small"
                        style="width: 140" class="subset-select">
                        <el-option v-for="subset in subsetsDirs" :key="subset.id" :label="subset.image_dir"
                            :value="subset.image_dir" />
                    </el-select>
                    <el-button type="primary" plain size="small" class="subset-btn" @click="onConfigSubset(subset)">{{
                        subset.editing ? '确定' : '编辑' }}</el-button>
                </div>
            </div>
        </div>
        <template #footer>
            <span class="dialog-footer">
                <el-button v-if="_modelSettingStatus === 1" type="primary" plain
                    @click="_modelSettingStatus = 0">上一步</el-button>
                <el-button type="primary" @click="onDatasetSelected()"> {{ _modelSettingStatus ? '确 定' : '下一步'
                    }}</el-button>
                <el-button @click="onDatasetCancel()">取消</el-button>
            </span>
        </template>
    </el-dialog>
</template>

<script setup>
import { onMounted, ref, inject } from 'vue';
import API from '@/js/api';
import { InfoFilled, MagicStick, Promotion, Histogram } from '@element-plus/icons-vue';
import TypeBar from '../TypeBar.vue';

let vueApp = inject('vueApp');
const emit = defineEmits(['showModelsLocal']);

// 模型卡片列表属性
let _cardlist = ref([]);
let _current_model = {};

// 选择数据集对话框相关属性
let _dialogFormVisible = ref(false);
let _modelSettingStatus = ref(0);
let _model_configs = ref([]);
let _model_config = ref(null);
let _model_total_params = ref(null);
let _model_trainable_params = ref(null);

let _dataset_type = ref('detection');
let _datasets = ref([]);
let _current_index = ref(-1);

// 数据集的细分属性
const subsetsInfo = ref({});
const subsetsDirs = ref([]);

function showDialog(show) {
    _dialogFormVisible.value = show;
    vueApp.monitorKeyEvent(!show);
}

function handleBeforeClose(done) {
    vueApp.monitorKeyEvent(true);
    done();
}

function formattedSubsetType(subset_type) {
    let types = {
        train: '训练集',
        val: '验证集',
        test: '测试集'
    };
    return types[subset_type];
}

async function onConfigSubset(subset) {
    // console.log('onConfigSubset', subset);
    if (subset.editing == true) {
        let subset_directory = subsetsDirs.value.find((object) => object.image_dir === subset.image_dir);
        // console.log('subset_directory = ', subset_directory);
        let subsetInfo = {
            id: subset.id,
            dataset_id: subset.dataset_id,
            image_dir: subset.image_dir,
            label_dir: subset_directory.label_dir
        };

        let result = await API.invoke('UpdateSubset', subsetInfo);
        // console.log(result);
        if (result.code == 0) {
            console.log(`result = `, result);
        }
    }
    subset.editing = !subset.editing;
}

async function handleRowClick(row, column, event) {
    let rowIndex = _datasets.value.findIndex((item) => item.id === row.id);
    _current_index.value = rowIndex;

    // 查询数据集的详情
    let result = await API.invoke('GetSubsets', { dataset_id: row.id });
    // console.log(result);
    if (result.code == 0) {
        subsetsInfo.value = result.msg
            .filter((subset) => subset.subset_type !== 'directory')
            .map((subset) => ({
                ...subset,
                editing: false
            }));
        subsetsDirs.value = result.msg.filter((subset) => subset.subset_type === 'directory');
    }
}

function headerCellStyle({ row, index }) {
    return {
        color: '#222',
        'background-color': '#efefef'
    };
}

function cellStyle({ row, column, rowIndex, columnIndex }) {
    // console.log(row, column, rowIndex, columnIndex);
    let style = {};

    // console.log(`row.id = ${row.id}, _current_index = ${_current_index.value}`);
    if (rowIndex == _current_index.value) {
        style['font-weight'] = 'bold';
    }

    return style;
}

// ===============================================
async function handleTrainModel(card) {
    // console.log('handleTrainModel card = ', card);
    let result = await API.invoke('GetModelConfigs', { model_id: card.id });
    if (result.code === 0) {
        // 读取模型的所有配置
        _model_configs.value = result.msg;
        _model_config.value = null;
        _model_total_params.value = null;
        _model_trainable_params.value = null;
        _current_model = card;
        showDialog(true);
    }
}

function onDatasetCancel() {
    _modelSettingStatus.value = 0;
    showDialog(false);
}

async function onChangeModelConfig() {
    // console.log('onChangeModelConfig config_name = ', _model_config.value);
    let result = await API.invoke('GetModelParams', {
        model_id: _current_model.id,
        config_name: _model_config.value
    });
    console.log(result);
    if (result.code == 0) {
        _model_total_params.value = result.msg.total_params;
        _model_trainable_params.value = result.msg.trainable_params;
    }
}

async function onDatasetSelected() {
    if (_modelSettingStatus.value === 0) {
        if (!_model_config.value) {
            ElMessage.error(`未选择模型配置！`);
            return;
        }
        _modelSettingStatus.value = 1;
    } else {
        if (_current_index.value >= 0) {
            // 读取模型配置和数据集配置
            let dataset = _datasets.value[_current_index.value];
            let train_cfg = {
                config_name: _model_config.value,
                dataset_type: 'coco'
            };

            let result = await API.invoke('CreateLocalModel', {
                model_id: _current_model.id,
                model_name: _current_model.name,
                model_eng_name: _model_config.value,
                model_type: _current_model.type,
                model_subtype: _current_model.subtype,
                dataset_id: dataset.id,
                dataset_name: dataset.dataset_name,
                remote_id: 'local',
                env_name: 'mmdet',
                train_cfg: JSON.stringify(train_cfg)
            });

            console.log('onCreateLocalModel ret = ', result);
            if (result.code == 0) {
                showDialog(false);
                emit('showModelsLocal');
            }
        }
    }
}

function handleModelInfo(card) {
    console.log('handleModelInfo card = ', card);
}

function handleModelInfer(card) {
    console.log('handleModelInfer card = ', card);
}

function handleModelEval(card) {
    console.log('handleModelEval card = ', card);
}

// 获取云端模型模版的列表
async function GetCloudModels() {
    // 显示加载中，并调用本地服务
    const loading = ElLoading.service({
        lock: true,
        text: '加载中...',
        background: 'rgba(0, 0, 0, 0.7)'
    });
    let result = await API.invoke('GetCloudModels', {});
    loading.close();

    // console.log(result);
    if (result.code == 0) {
        _cardlist.value = result.msg;
        // _cardlist.value.push(...result.msg);
        // _cardlist.value.push(...result.msg);
        // _cardlist.value.push(...result.msg);
    }
}

// 获取本地所有数据集列表
async function getDatasetList() {
    // 显示加载中，并调用本地服务
    const loading = ElLoading.service({
        lock: true,
        text: '加载中...',
        background: 'rgba(0, 0, 0, 0.7)'
    });
    let result = await API.invoke('GetDatasetList', {
        dataset_type: _dataset_type.value
    });
    loading.close();

    // console.log(result.msg);
    if (result.code == 0) {
        _datasets.value = result.msg;
    } else {
        _datasets.value = [];
    }
}

onMounted(async () => {
    await GetCloudModels();
    await getDatasetList();
});
</script>

<style scoped>
.model-cards-container {
    display: grid;
    padding: 2px 6px 2px 6px;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    background-color: rgb(249, 248, 248);
    overflow-y: auto;
}

.model-card {
    position: relative;
    background-color: rgb(255, 255, 255);
    height: 188px;
    box-shadow: 0px 0px 2px 2px rgba(229, 229, 232, 0.5);
    padding: 20px 15px 5px 20px;
    overflow-wrap: break-word;
    word-break: break-word;
    min-width: 300px;
}

.model-name {
    font-size: 20px;
    font-weight: 800;
    margin-bottom: 5px;
    white-space: nowrap;
}

.model-eng-name {
    font-size: 14px;
    margin-bottom: 15px;
    white-space: nowrap;
}

.model-tags {
    margin-bottom: 5px;
}

.model-tag {
    margin-right: 5px;
}

.model-desc {
    font-size: 14px;
    color: rgb(170, 170, 171);
    margin-bottom: 15px;
    min-height: 40px;
    max-height: 40px;
    overflow: hidden;
}

.model-footer {
    display: flex;
    white-space: nowrap;
    color: rgb(150, 150, 152);
}

.model-params-size {
    font-size: 12px;
    margin-right: 5px;
}

.model-update-time {
    font-size: 12px;
    margin-right: 5px;
}

.train-btn {
    position: absolute;
    right: 15px;
    bottom: 12px;
}

.more-btn {
    position: absolute;
    right: 20px;
    top: 15px;
}

.more-icon {
    padding: 2px 2px 0px 0;
    width: 1.4em;
    height: 1.4em;
    color: rgb(18, 136, 227);
    font-weight: 700;
}

.datasets-panel {
    background-color: rgb(255, 255, 255);
    width: 100%;
    height: 160px;
    overflow: auto;
    border: solid 1px;
    border-color: #cfcfcf;
}

.subsets-panel {
    margin-top: 10px;
    padding: 10px 5px;
    border: solid 1px;
    border-color: #cfcfcf;
}

.subset-title {
    font-size: 14px;
    font-weight: 800;
    margin: 5px;
    white-space: nowrap;
}

.subset-info {
    display: flex;
    align-items: center;
    margin: 5px;
    width: 100%;
}

.subset-type {
    flex: 1;
    white-space: nowrap;
    font-weight: 800;
    overflow: hidden;
    text-overflow: ellipsis;
    color: rgb(151, 151, 151);
    margin-left: 10px;
}

.subset-dir {
    display: flex;
    margin: 0px 10px;
}

.subset-select {
    margin-right: 5px;
    flex-shrink: 0;
    width: 140px;
}

.subset-btn {
    margin-right: 15px;
}

.directory-item-title-icon {
    padding: 0px 2px;
    width: 16px;
    height: 16px;
    color: rgb(223, 173, 36);
}

.model-configs-panel {
    display: flex;
    margin: 3px;
    padding: 5px;
    justify-content: space-between;
}

.model-configs-title {
    font-size: 14px;
    margin: 6px 15px 5px 5px;
    width: 70px;
}

.model-configs-selector {
    flex: 1;
}

.model-configs-value {
    font-size: 16px;
    font-weight: 800;
    margin: 9px 15px 5px 5px;
}
</style>
